#include "PrecompiledHeader.h"
#include "CMouse.h"

/*--------------------------------------------------------------------------*/
CMouse* g_Mouse = NULL;
/*--------------------------------------------------------------------------*/

CMouse::CMouse() :
	IEngMod("CMouse")
{
	ViaMain::CallOnLoop(this, 0, 20, "Update");

	this->m_leftButton = false;
	this->m_rightButton = false;

	AssertModule(g_Shell);

	this->var_mouse_speed = g_Shell->AddVar("mouse_speed", 2.0f);
	this->var_mouse_wrap = g_Shell->AddVar("mouse_wrap", 1);
}

/*--------------------------------------------------------------------------*/

CMouse::~CMouse()
{

}

/*--------------------------------------------------------------------------*/

bool CMouse::GetKeyState(uint keyToCheck) const
{
	if (keyToCheck == EKey::LMB)
	{
		return this->m_leftButton;
	}

	if (keyToCheck == EKey::RMB)
	{
		return this->m_rightButton;
	}

	if (keyToCheck == EKey::WheelUp)
	{
		return this->m_wheelUp;
	}

	if (keyToCheck == EKey::WheelDown)
	{
		return this->m_wheelDown;
	}

	return false;
}

/*--------------------------------------------------------------------------*/

void CMouse::SetKeyState(uint keyToCheck, bool state)
{
	if (keyToCheck == EKey::LMB)
	{
		this->m_leftButton = state;
	}

	if (keyToCheck == EKey::RMB)
	{
		this->m_rightButton = state;
	}

	if (keyToCheck == EKey::WheelUp)
	{
		this->m_wheelUp = state;
	}

	if (keyToCheck == EKey::WheelDown)
	{
		this->m_wheelDown = state;
	}
}

/*--------------------------------------------------------------------------*/

void CMouse::OnUpdate()
{
	this->m_wheelUp = false;
	this->m_wheelDown = false;

	std::list<SDL_Event>& events = g_Sdl->GetEvents();

	for (std::list<SDL_Event>::iterator it = events.begin(); it != events.end(); ++it)
	{
		SDL_Event event = *it;

		if (event.type == SDL_MOUSEBUTTONDOWN)
		{
			if (event.button.button == SDL_BUTTON_LEFT)
			{
				this->m_leftButton = true;
			}
			else if (event.button.button == SDL_BUTTON_RIGHT)
			{
				this->m_rightButton = true;
			}
			else if (event.button.button == SDL_BUTTON_WHEELUP)
			{
				this->m_wheelUp = true;
			}
			else if (event.button.button == SDL_BUTTON_WHEELDOWN)
			{
				this->m_wheelDown = true;
			}
		}
		else if (event.type == SDL_MOUSEBUTTONUP)
		{
			if (event.button.button == SDL_BUTTON_LEFT)
			{
				this->m_leftButton = false;
			}
			else if (event.button.button == SDL_BUTTON_RIGHT)
			{
				this->m_rightButton = false;
			}
		}
	}

	if (this->var_mouse_wrap->GetBool() == false)
	{
		glm::ivec2 currentMouse;
		SDL_GetMouseState(&currentMouse.x, &currentMouse.y);

		this->m_movement.x = (float)(currentMouse.x) - this->m_position.x;
		this->m_movement.y = (float)(currentMouse.y) - this->m_position.y;

		this->m_position = glm::vec2((float) currentMouse.x, (float) currentMouse.y);
	}
	else
	{
		glm::ivec2 currentMouse;
		SDL_GetMouseState(&currentMouse.x, &currentMouse.y);

		currentMouse.y = g_Settings->GetResolutioni().y - currentMouse.y;

		if (currentMouse != g_Settings->GetResolutioni() / 2)
		{
			SDL_WarpMouse((Uint16) g_Settings->GetResolutioni().x / 2, (Uint16) g_Settings->GetResolutioni().y / 2);

			this->m_movement.x = (float)(currentMouse.x) - g_Settings->GetResolutionf().x / 2.0f;
			this->m_movement.y = (float)(currentMouse.y) - g_Settings->GetResolutionf().y / 2.0f;

			this->m_movement = this->m_movement * (this->var_mouse_speed->GetFloat() / 5.0f);
			this->m_position = this->m_position + this->m_movement;

			if (this->m_position.x < 0.0f)
			{
				this->m_position.x = 0.0f;
			}
			else if (this->m_position.x > g_Settings->GetResolutionf().x)
			{
				this->m_position.x = g_Settings->GetResolutionf().x;
			}

			if (this->m_position.y < 0.0f)
			{
				this->m_position.y = 0.0f;
			}
			else if (this->m_position.y > g_Settings->GetResolutionf().y)
			{
				this->m_position.y = g_Settings->GetResolutionf().y;
			}

			this->m_direction = glm::normalize(g_Settings->GetResolutionf() / 2.0f - this->m_position);
		}
		else
		{
			this->m_movement = glm::vec2();
		}
	}
}

/*--------------------------------------------------------------------------*/

const glm::vec2& CMouse::GetMovement() const
{
	return this->m_movement;
}

/*--------------------------------------------------------------------------*/

const glm::vec2& CMouse::GetPosition() const
{
	return this->m_position;
}

/*--------------------------------------------------------------------------*/

void CMouse::SetCursor(const glm::vec2& npos)
{
	this->m_position = npos;
}

/*--------------------------------------------------------------------------*/

void CMouse::OnLoop(uint i)
{
	switch (i)
	{
	case 0:
	{
		this->OnUpdate();
		//this->BenchmarkLog("CMouse::OnUpdate");
		break;
	}
	}
}

/*--------------------------------------------------------------------------*/

const glm::vec2& CMouse::GetDirection() const
{
	return this->m_direction;
}

/*--------------------------------------------------------------------------*/

